package com.imxinxin.common.tools.json;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import java.io.IOException;
import java.lang.reflect.Type;
import java.text.*;
import java.util.Date;

public class JsonTool {

    private final static ObjectMapper objectMapper;
    private final static Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").disableHtmlEscaping().create();

    static {
        objectMapper = new ObjectMapper();
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        objectMapper.getSerializerProvider().setNullKeySerializer(new DtoNullKeySerializer());
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        objectMapper.setDateFormat(new DateFormat() {
            String format = "yyyy-MM-dd HH:mm:ss.SSS";

            @Override
            public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) {
                if (date == null) {
                    return toAppendTo;
                }
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
                return toAppendTo.append(simpleDateFormat.format(date));
            }

            @Override
            public Date parse(String source, ParsePosition pos) {
                if (source == null) {
                    return null;
                }
                try {
                    return new SimpleDateFormat(format).parse(source);
                } catch (ParseException e) {
                    throw new RuntimeException(e);
                }
            }

        });
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addDeserializer(Boolean.class, new JsonDeserializer<Boolean>() {
            @Override
            public Boolean deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
                JsonToken currentToken = p.getCurrentToken();
                if (currentToken.equals(JsonToken.VALUE_STRING)) {
                    String text = p.getText();

                    if ("Y".equals(text) || "1".equals(text)) {
                        return Boolean.TRUE;
                    } else {
                        return Boolean.FALSE;
                    }
                }

                return p.getBooleanValue();
            }
        });
        objectMapper.registerModule(simpleModule);

    }

    public static String toJson(Object o) {
        try {
            return objectMapper.writeValueAsString(o);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> T fromJson(String json, Class<T> clz) {
        try {
            return objectMapper.readValue(json, clz);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> T fromJson(String json, TypeR<T> type) {
        try {
            return objectMapper.readValue(json, type);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> T fromJson(String json, TypeT<T> type) {
        return gson.fromJson(json, type.getType());
    }
    public static <T> T fromJson(String json, Type typeOfT) {
        return gson.fromJson(json, typeOfT);
    }

}
